package com.zh.common.update

import android.content.Intent
import android.net.Uri
import android.os.Build
import android.util.Log
import androidx.core.content.FileProvider
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.ToastUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import java.net.HttpURLConnection
import java.net.URL
import kotlin.system.exitProcess

class UpdateService private constructor(
    private val activity: FragmentActivity,
    private var downloadUrl: String?,
    private var filePath: String?,
    private var listener: DownloadListener?,
    private var versionCode: Int = 0
) {

    //下载apk
    fun download() {
        if (AppUtils.getAppVersionCode() >= versionCode) {
            ToastUtils.showShort("当前已是最新版本")
            return
        }
        if (downloadUrl.isNullOrEmpty()) {
            throw KotlinNullPointerException("downloadUrl is not null")
        }
        activity.lifecycleScope.launch(Dispatchers.IO) {
            withContext(Dispatchers.Main) { listener?.onStart() }
            val file = if (filePath.isNullOrEmpty()) {
                File(activity.externalCacheDir, "apk")
            } else {
                File(filePath!!)
            }
            if (file.exists()) file.delete()
            file.createNewFile()
            var connection: HttpURLConnection? = null
            try {
                connection = URL(downloadUrl).openConnection() as HttpURLConnection?
                connection?.let { connection ->
                    connection.instanceFollowRedirects = true
                    connection.requestMethod = "GET"
                    connection.connectTimeout = 8000
                    connection.readTimeout = 5000
                    connection.doInput = true
                    connection.doInput = true
                    connection.useCaches = false

                    if (connection.responseCode == HttpURLConnection.HTTP_MOVED_TEMP ||
                        connection.responseCode == HttpURLConnection.HTTP_MOVED_PERM
                    ) {//重定向
                        downloadUrl = URL(connection.getHeaderField("Location")).toString()
                        download()
                    } else if (connection.responseCode == HttpURLConnection.HTTP_OK
                        || connection.responseCode == HttpURLConnection.HTTP_PARTIAL) {
                        var fileSize = connection.contentLength.toLong()
                        if (fileSize < 0) {
                            Log.d("downloadFile", "无法获取文件大小")
                            fileSize = 1024
                        }
                        var fileSizeDownloaded: Long = 0
                        val `in` = connection.inputStream
                        val out = FileOutputStream(file)
                        val buf = ByteArray(4096)
                        try {
                            while (true) {
                                val read = `in`.read(buf)
                                if (read == -1) {
                                    break
                                }
                                out.write(buf, 0, read)
                                fileSizeDownloaded += read.toLong()

                                //计算当前下载百分比，并经由回调传出
                                withContext(Dispatchers.Main) {
                                    val progress = (100 * fileSizeDownloaded / fileSize).toInt()
                                    listener?.onProgress(progress, fileSize)
                                }
                                Log.d(
                                    "downloadFile",
                                    "file download: $fileSizeDownloaded of $fileSize"
                                )
                            }
                            Log.d("downloadFile", "下载成功:" + file.name)
                            withContext(Dispatchers.Main) {
                                listener?.onSuccess(file.absolutePath)
                                if (listener == null) {//自动安装
                                    jumpInstance(file.absolutePath)
                                }
                            }
                        } catch (e: Exception) {
                            e.printStackTrace()
                            Log.d("downloadFile", "下载失败:" + file.name)
                            withContext(Dispatchers.Main) { listener?.onError(e.message.toString()) }
                        } finally {
                            out.flush()
                            out.close()
                            `in`.close()
                        }
                    } else {
                        Log.d("downloadFile", "服务器错误：${connection.responseCode}")
                        withContext(Dispatchers.Main) {
                            listener?.onError("服务器错误：${connection.responseCode}")
                        }
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
                Log.d("downloadFile", "下载失败:" + file.name)
                withContext(Dispatchers.Main) { listener?.onError(e.message.toString()) }
            } finally {
                connection?.disconnect()
                withContext(Dispatchers.Main) { listener?.onEnd() }
            }
        }
    }

    //跳转安装apk
    fun jumpInstance(path: String) {
        val intent = Intent(Intent.ACTION_VIEW)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            val apkUri = FileProvider.getUriForFile(
                activity, "${activity.packageName}.fileprovider", File(path)
            )
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
        } else {
            intent.setDataAndType(
                Uri.fromFile(File(path)), "application/vnd.android.package-archive"
            )
        }
        activity.startActivity(intent)
        activity.window.decorView.postDelayed({ exitProcess(0) }, 10)
    }

    class Builder(private val activity: FragmentActivity) {
        private var downloadUrl: String? = null
        private var filePath: String? = null
        private var listener: DownloadListener? = null
        private var versionCode: Int = 0

        fun setDownloadUrl(downloadUrl: String): Builder {
            this.downloadUrl = downloadUrl
            return this
        }

        fun setFilePath(filePath: String): Builder {
            this.filePath = filePath
            return this
        }

        fun setVersionCode(versionCode: Int): Builder {
            this.versionCode = versionCode
            return this
        }

        fun setDownloadListener(listener: DownloadListener): Builder {
            this.listener = listener
            return this
        }

        fun build(): UpdateService {
            return UpdateService(activity, downloadUrl, filePath, listener, versionCode)
        }
    }
}
